﻿<html xmlns:MSHelp="http://msdn.microsoft.com/mshelp" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xanx="http://schemas.microsoft.com/developer/xanx/2005"><head><META http-equiv="Content-Type" content="text/html; charset=utf-8"><META NAME="save" CONTENT="history"><title>Client/Server Sample</title>
<style><!--
/***********************************************************
 *             SCRIPT-SUPPORTING STYLES
 ***********************************************************/

/* Defines the userData cache persistence mechanism. */
.userDataStyle
{
	behavior: url(#default#userData);
}

/* Used to save the scroll bar position when navigating away from a page. */
div.saveHistory
{
	behavior: url(#default#saveHistory);
}

/* Formats the expand/collapse images for all collapsible regions. */
img.toggle
{
	border: 0;
	margin-right: 5;
}

/* Formats the Language filter drop-down image. */
img#languageFilterImage
{
	border: 0;
	margin-left: 0;
	vertical-align: middle;
}

/* Formats the Members Options filter drop-down image. */
img#membersOptionsFilterImage
{
	border: 0;
	margin-left: 0;
	vertical-align: middle;
}

/* Formats the Collapse All/Expand All images. */
img#toggleAllImage
{
	margin-left: 0;
	vertical-align: middle;
}

/* Supports XLinks */
MSHelp\:link
{
 	text-decoration: underline;
	color: #0000ff; 
	hoverColor: #3366ff;
	filterString: ;
}


body
	{
	background:	#FFFFFF;
	color: #000000;
	font-family:	Verdana;
	font-size: medium;
	font-style: normal;
	font-weight: normal;
	margin-top:	0;
	margin-bottom:	0;
	margin-left:	0;
	margin-right:	0;
	width:	100%;
	/*font-size: 110%;*/
	}

div.section
	{
	margin-left: 15px;
	}

div.hxnx5
	{
	margin-left: 1.5em;
	}

/* Font for all headings */	
h1, h2, h3, h4, h5, h6
	{
	font-family: Verdana, Arial, Helvetica, sans-serif;
	margin-top: 18;
	margin-bottom: 8; 
	font-weight: bold;
	}
h1
	{
	font-size: 130%;
	color: #003399;
	}
div#scrollyes h1 /* Changes font size for full-scrolling topic */
	{
	font-size: 150%;
	}
h2
	{
	font-size: 125%;
	}
h3
	{
	font-size: 115%;
	margin-top: 9;
	margin-bottom: 4; 
	}
h4
	{
	font-size: 115%;
	margin-top: 9;
	margin-bottom: 4; 
	}
h5
	{
	font-size: 100%;
	margin-top: 9;
	margin-bottom: 4; 
	}
h6
	{
	font-size: 100%;
	margin-top: 9;
	margin-bottom: 4; 
	}

ul p, ol p, dl p
	{
	margin-left: 0em;
	}

p
	{
	margin-top: .6em;
	margin-bottom: .6em;
	}
	
td p
	{
	margin-top: 0.0em;
	margin-bottom: 0.6em;
	}

dd p
	{
	margin-top: 0.0em;
	margin-bottom: 0.6em;
	}

.image
	{
	text-align: center;
	}

dl
	{
	margin-top: 0em; 
	margin-bottom: 1.3em;
	}

dd
	{
	margin-bottom: 0em;
	margin-left: 0;
	}

dl.glossary dd 
{
	margin-bottom: 0em;  
	margin-left: 1.5em; 
}

dt
	{
	margin-top: .6em;
	margin-bottom: 1;
	}

ul, ol
	{
	margin-top: 0.6em;
	margin-bottom: 0.6em; 	
	}
	
ol
	{
	margin-left: 2.5em; 
	
	}	
	
ul
	{
	list-style-type: disc; 
	margin-left: 1.9em; 
	}

li
	{
	margin-bottom: 0.4em;
	}

ul ol, ol ol
	{
	list-style-type: lower-alpha;
	}

pre
	{
	margin-top: .6em;
	margin-bottom: .6em; 
	}

pre
	{
	font: 105% Lucida, mono; 
	color: #000066;
	}

code
{
	font-family: Monospace, Courier New, Courier;
	font-size: 105%;
	color:	#000066;
}

table.userdata td 
	{
	background: #ffffff;
	background-color: #F5F5F5;
	border-color: #ffffff;
	border: none;
	}	
table.clsWarning
	{
	background: #ffffff;
	padding: 0px;
	margin: 0px;
	border: none;
	}
table.clsWarning td
	{
	padding: 0px;
	margin: 0px;
	background: #ffffff;
	vertical-align: middle;
	font-size: 70%;
	}

div#mainSection table
	{
	width: 98%;
	background: #ffffff;
	margin-top: 5px;
	margin-bottom: 5px;
	}

div#mainSection table th
	{ 
	padding: 5px 6px;
	background: #EFEFF7;
	text-align: left;
	font-size: 70%;
	vertical-align: bottom;
	border-bottom: 1px solid #C8CDDE;
	}
div#mainSection table td
	{ 
	padding: 5px 5px;
	background: #F7F7FF;
	vertical-align: top;
	font-size: 70%;
	border-bottom: 1px solid #D5D5D3;
	}

div#syntaxCodeBlocks table th
	{
	padding: 1px 6px;
	color: #000066;
	}

div#syntaxCodeBlocks table td
	{
	padding: 1px 5px;
	}

/* Applies to the running header text in the first row of the upper table in the
   non-scrolling header region. */
span#runningHeaderText
{
	color: #003399;
	font-size: 90%;
	padding-left: 13;
}

/* Applies to the topic title in the second row of the upper table in the
   non-scrolling header region. */
span#nsrTitle
{
	color: #003399;
	font-size: 120%;
	font-weight: 600;
	padding-left: 13;
}

/* Applies to everything below the non-scrolling header region. */
div#mainSection
{
	font-size: 70%;
	width: 100%;
}

/* Applies to everything below the non-scrolling header region, minus the footer. */
div#mainBody
{
	font-size: 90%;
	margin-left: 15;
	margin-top: 10;
	padding-bottom: 20;
}

/* Adds right padding for all blocks in mainBody */
div#mainBody p, div#mainBody ol, div#mainBody ul, div#mainBody dl
{
	padding-right: 5;
}

div#mainBody div.alert, div#mainBody div.code, div#mainBody div.tableSection
{
	width:98.9%;
}

div.alert p, div.code p
{
	margin-top:5;
	margin-bottom:8;
}

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Note Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
div#mainSection div.alert table
{
	border: 0;
}

div#mainSection div.alert table th
{
	padding-top: 0;
	padding-bottom: 0;
	padding-left: 5;
	padding-right: 5;
}

div#mainSection div.alert table td
{
	padding-left: 5;
	padding-right: 5;
}

img.note
{
	border: 0;
	margin-left: 0;
	margin-right: 3;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - End Note Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Non-scrolling Header Region Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Applies to the entire non-scrolling header region. */
div#header
{
	background-color: #D4DFFF;
	padding-top:	0;
	padding-bottom:	0;
	padding-left:	0;
	padding-right:	0;
	width:	100%;
}

/* Applies to both tables in the non-scrolling header region. */
div#header table
{
	margin-top:	0;
	margin-bottom: 0;
	border-bottom-color: #C8CDDE;
	border-bottom-style: solid;
	border-bottom-width: 1;
	background: #D4DFFF;
	width:	100%;
}

/* Applies to cells in both tables in the non-scrolling header region. */
div#header table td
{
	color: #0000FF;
	font-size: 70%;
	padding-right: 20;
	padding-top: 1;
	padding-bottom: 1;
	border: none;
	background: #D4DFFF;
}

/* Applies to the last row in the upper table of the non-scrolling header region. Text 
   in this row includes See Also, Constructors, Methods, and Properties. */
div#header table tr#headerTableRow3 td
{
	padding-bottom: 2;
	padding-top: 5;
	padding-left: 15;
}

/* Applies to the lower table in the non-scrolling header region. Text in this table
   includes Collapse All/Expand All, Language Filter, and Members Options. */
div#header table#bottomTable
{
	border-top-color: #FFFFFF;
	border-top-style: solid;
	border-top-width: 1;
	text-align: left;
	padding-left: 15;
}


blockquote
	{
	margin-left: 3.8em;
	margin-right: 3.8em;
	margin-top: .6em;
	margin-bottom: .6em;
	}

sup
	{
	text-decoration: none;
	font-size: smaller; 
	}

a:link
	{
	color: #0000FF;
/*    font-weight: bold */
	}
	
a:visited
	{
	color: #0000AA;
/*    font-weight: bold	*/
	}
	
a:hover
	{
	color: #3366FF;
/*    font-weight: bold */
	}
	
.label
	{
	font-weight: bold; 
	margin-top: 1em;
	margin-left: -26px;
	}
	
.tl
	{
	margin-bottom: .75em; 
	}
	
.atl
	{
	padding-left: 1.5em;
	padding-bottom: .75em; 
	}
	
.cfe
	{
	font-weight: bold; 
	}
	
.mini
	{
	font-size: smaller;
	}
	
.dt
	{
	margin-bottom: -.6em; 
	}
	
.indent
	{
	margin-left: 1.9em; 
	margin-right: 1.9em;
	}

.product
	{
	text-align: right;
	color: #333333;
	font-size: smaller;
	font-style: italic;
	}

.buttonbarshade
	{
	position: relative;
	margin: 0;
	left: 0px;
	top: 2;
	width: 50%;
	height: 40px;
	}

.buttonbartable
	{
	position: absolute;
	margin: 0;
	padding:0;
	border:0;
	left:0px;
	top: 2;
	width: 100%;
	height: 40px;
	}

/* background color, font for header */ 
table.buttonbartable td, table.buttonbarshade td
	{
	background: #ffffff; /*#5177B8; #80C615;*/
	border-left: 0px solid #80C615;
	margin: 0;
	padding: 0px 0px 0px 0px;
	font-family: Impact, sans-serif;
	font-size: 14pt;
	}

table.buttonbartable td.button1
	{
	background: #5177B8; /*#80C615;*/;
	padding: 0;
	font-weight: bold;
	text-align: center;
	cursor: hand;
	}

table.buttonbartable td.button2
	{
	background: #5177B8; /*#80C615;*/;
	font-weight: bold;
	text-align: center;
	}

table.buttonbartable td.button3
	{
	background: #5177B8; /*#80C615;*/;
	font-weight: bold;
	text-align: center;
	}

table.buttonbartable td.runninghead
	{
	padding-left: 0px;
	font-style: italic;
	text-align: left;
	}

.version
	{
	text-align: left;
	color: #000000;
	margin-top: 3em;
	margin-left: -26px;
	font-size: smaller;
	font-style: italic;
	}

.lang, .ilang
	{
	color: #0000ff;
	font: normal 7pt Arial, Helvetica, sans-serif;
	}

div.langMenu
	{
	position: absolute;
	z-index: 1;
	width: 96pt;
	padding: 8pt;
	visibility: hidden;
	border: 1px solid #000000;
	background: #ffffd0;
	}

div.langMenu ul
	{
	padding-left: 2em;
	margin-left: 0;
	}

div.filtered
	{
	margin: 4pt 0 8pt -26px;
	padding: 4px 4px 8px 26px;
	width: 100%;
	border: 2px solid #aaaacc;
	background: #ffffff;
	}

div.filtered2
	{
	margin: 4pt 0 8pt -26px;
	padding: 4px 4px 8px 26px;
	width: 100%;
	border: none;
	background: #ffffff;
	}

div.filtered h1, div.filtered h2, div.filtered h3, div.filtered h4
	{
	margin-left: -22px;
	}

div.filtered span.lang
	{
	position: relative;
	left: -22px;
	}

div.reftip
	{
	position: absolute;
	z-index: 1;
	padding: 8pt;
	visibility: hidden;
	border: 1px solid #000000;
	background: #ffffd0;
	}

a.synParam
	{
	color: #0000FF;
	/*color: #3F7800;*/ 	
	/*color: #8DC54F;*/
	text-decoration: none;
    font-weight: normal;
	}

a.synParam:hover
	{
	text-decoration: underline;
    font-weight: normal;
	}

div.sapop
	{
	position: absolute;
	z-index: 1;
	left: 26px;
	width: 100%;
	padding: 10px 10px 10px 36px;
	visibility: hidden;
	border: 1px solid #000000;
	background: #ffffd0;
	}

div.footer
	{
	width: 100%;
	border: none;
	background: #ffffff;
	margin-top: 18pt;
	padding-bottom: 12pt;
	color: #0000FF;
	/*color: #228B22; */
	text-align: center;
	font-size: 76%;
	}

div.preliminary
	{
	margin-top: 8pt;
	padding-bottom: 12pt;
	color: #A0A0A0;
	}

/* A procedure section. eg. 'To create a file', 'To add a value' */
div.proc
    {
	margin-left: 0.5em; 
    }
     
/* The title of a 'procedure' section. */
div.proc h3
    {
	font-family: Verdana, Arial, Helvetica, sans-serif;
	font-weight: bold;
	font-size: 115%;
	margin-top: 1em;
	margin-bottom: 0.4em;
	margin-left: -0.5em; 
	color: #003399;
    }

div.proc ul
    {
    margin-left: 1.5em;
    }

div.proc ol
    {
    margin-left: 2.0em;
    }
      
.note
	{
	margin-left: 14pt;
	margin-right: 12pt;
	}

.indent1
	{
	margin-left: 12pt;
	}

.indent2
	{
	margin-left: 24pt;
	}

.indent3
	{
	margin-left: 36pt;
	}

p.proch
	{
	padding-left: 16px;
	}

p.proch img
	{
	position: relative; 
	vertical-align: top;
	left: -18px; 
	margin-right: -14px; 
	margin-bottom: -18px;
	}
	
div.clsPlatSpec
{
	background-color:#FFF8DC;
	border-style:solid;
	border-width:1pt 0pt 0pt 1pt;
	border-color:#ffE4C4;
	margin-top:0.6em;
	width:100%;
}


/* Applies to the language labels in the Language Filter drop-down list. */
.languageFilter
{
	color:	#0000FF;
	cursor:hand;
	text-decoration:underline;
	padding-bottom:4;
}

/* Dropdown areas */

#languageSpan {
	position: absolute;
	visibility: hidden;
	border-style: solid;
	border-width: 1px;
	border-color: #C8CDDE;
	background: #d4dfff;
	padding: 4px;
	font-size: 70%;
}

#membersOptionsSpan {
	position: absolute;
	visibility: hidden;
	border-style: solid;
	border-width: 1px;
	border-color: #C8CDDE;
	background: #d4dfff;
	padding: 4px;
	font-size: 70%;
}
--></style>

<xml>
<MSHelp:TOCTitle Title="Client/Server Sample" />
<MSHelp:RLTitle Title="Client/Server Sample" />
<MSHelp:Keyword Index="A" Term="O:Microsoft.Xna.ClientServer" />
<MSHelp:Keyword Index="A" Term="1d2f92eb-3c6d-1b5d-a7e8-c437f1e59959" />
<MSHelp:Keyword Index="K" Term="Client/Server Sample" />
<MSHelp:Attr Name="ProjType" Value="LocalProj" />
<MSHelp:Attr Name="ProjType" Value="XNA_20" />
<MSHelp:Attr Name="DocSet" Value="XNA" />
<MSHelp:Attr Name="DocSet" Value="ExpressLibVS" />
<MSHelp:Attr Name="DocSet" Value="C#" />
<MSHelp:Attr Name="Locale" Value="en-us" />
<MSHelp:Attr Name="AssetID" Value="1d2f92eb-3c6d-1b5d-a7e8-c437f1e59959" />
<MSHelp:Attr Name="TopicType" Value="kbOrient" />
</xml>
</head><body><div id="mainSection"><div id="mainBody">

  <h1>Client/Server Sample</h1>

  This sample implements a simple multiplayer network session, using a client/server network topology where each computer sends its player input to the server, which then updates the state of everyone in the session and sends the results back to the clients.

  <a name="ID2EK"></a><h1 class="heading">Sample Overview</h1><div id="ID2EK" class="hxnx1">
    

    <p>This sample shows the basics of how to create and join network sessions, and how to exchange data using a client/server network topology. Each player controls a tank, which they can drive around the screen while rotating the turret. The game simulation is run entirely on a single computer that has been designated as the server. Client computers send their player inputs to the server, which then sends the resulting game state back to each client. Game logic only ever runs on the server: the clients are effectively functioning as dumb terminals, responsible only for reading input and rendering the game world as described by the server.</p>

    <p>
      For an alternative way to handle networked game simulation, see the Peer-to-Peer sample, which implements the same tank movement using a peer-to-peer network topology.
    </p>

    <a name="ID2ES"></a><h2 class="subHeading">Minimum Shader Profile</h2><div id="ID2ES" class="hxnx2">
      
      <dl class="glossary">
        <dt>Vertex Shader Model 1.1</dt>
        <dt>Pixel Shader Model 1.1</dt>
      </dl>
    </div>

    <a name="ID2E5"></a><h2 class="subHeading">Sample Controls</h2><div id="ID2E5" class="hxnx2">
      
      <p>This sample uses the following keyboard and gamepad controls.</p>

      <table>
        <tr>
          <th>Action</th>
          <th>Keyboard Control</th>
          <th>Gamepad Control</th>
        </tr>
        <tr>
          <td>Create a session.</td>
          <td>
            <b>A</b>
          </td>
          <td>
            <b>A</b>
          </td>
        </tr>
        <tr>
          <td>Join a session.</td>
          <td>
            <b>B</b>
          </td>
          <td>
            <b>B</b>
          </td>
        </tr>
        <tr>
          <td>Move the tank.</td>
          <td>UP ARROW, DOWN ARROW, LEFT ARROW, RIGHT ARROW</td>
          <td>Left thumb stick</td>
        </tr>
        <tr>
          <td>Aim the turret.</td>
          <td>
            <b>A</b>, <b>D</b>, <b>W</b>, <b>S</b>
          </td>
          <td>Right thumb stick</td>
        </tr>
        <tr>
          <td>Exit the sample.</td>
          <td>ESC or ALT+F4</td>
          <td>
            <b>BACK</b>
          </td>
        </tr>
      </table>
    </div>
  </div>

  <a name="ID2EXD"></a><h1 class="heading">How the Sample Works</h1><div id="ID2EXD" class="hxnx1">
    

    <p>In a client/server game, the work of updating game logic, moving objects around, computing physics, checking for collisions, and so on, runs entirely on a single computer that has been chosen as the server. With the XNA Framework networking system, the server is just a regular computer that is also playing in the session. This is different to some Windows games that use a separate dedicated computer as their server.</p>

    <p>In this sample, the host computer is also used as the server. This does not always have to be the case, as games are free to choose whichever computer they like as their server (or none at all if they are using peer-to-peer networking). For instance a game might want to examine the ping times between every computer in the session, and choose the one with the lowest average ping as their server. The server does not mean anything special to the XNA Framework, so games are free to choose it however they wish. The host, on the other hand, does have a special built-in meaning. The host is the computer that originally created the session, and is responsible for advertising it via matchmaking so other machines can find and join it. The host is also responsible for deciding when to move between the lobby and gameplay states, using the <b>NetworkSession.StartGame</b> and <b>NetworkSession.EndGame</b> methods. If you enable <b>NetworkSession.AllowHostMigration</b>, a new host will automatically be selected if the previous host leaves (otherwise, the session will end when the host leaves). The host is always chosen for you by the XNA Framework, but the server is chosen by the game itself. In this sample, the two are always the same, because we simply reuse the host computer as our game server, thus simplifying our code and removing the need to explicitly choose which computer should be the server.</p>

    <p>This figure shows the data flow for a client/server game with three computers in the session:</p>

    <img src="Documentation/ClientServer.png">

    <p>You can see how all network data is routed through the host, Nimbus, and no packets are ever sent directly between the two clients, Rain and Drop.</p>

    <p>In psueduocode, client computers perform the following steps to send their user inputs to the server, then read the resulting game state:</p>

    <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>    foreach (LocalNetworkGamer gamer in networkSession.LocalGamers)
    {
        ReadLocalUserInputs(gamer);
        SendUserInputsToServer(gamer);

        while (gamer.IsDataAvailable)
        {
            ReadGameStateFromServer();
        }
    }</pre></pre></td></tr></table></span></div>

    <p>The server uses this more complicated update logic:</p>

    <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>    foreach (LocalNetworkGamer gamer in networkSession.LocalGamers)
    {
        // We can directly read the user inputs for our local gamers.
        ReadLocalUserInputs(gamer);

        // Inputs for remote gamers are read from network packets sent by the client.
        while (gamer.IsDataAvailable)
        {
            NetworkGamer sender;
            
            gamer.ReceiveData(packetReader, out sender);

            if (!sender.IsLocal)
            {
                ReadUserInputsFromClient(sender, packetReader);
            }
        }
    }

    // Update the game state for both local and remote players.
    foreach (NetworkGamer gamer in networkSession.AllGamers)
    {
        UpdateGamer(gamer);
    }

    // Send the resulting game state back out to our client computers.
    SendEntireGameStateToClients();</pre></pre></td></tr></table></span></div>

    <p>Client/server networking has several advantages over the alternative peer-to-peer topology:</p>
    <ul>
      <li>Because the entire game simulation runs at once on a single computer, client/server games are less likely to suffer from consistency problems.</li>
      <li>Because all decisions are made on a single server, it is harder for hackers to cheat by modifying their client game executables.</li>
    </ul>

    <p>But it also has some disadvantages:</p>
    <ul>
      <li>Client/server games usually require more network bandwidth than peer-to-peer games. The server must send information about every player to every client, thus sending a total of (<i>playerCount</i> * (<i>playerCount</i> − 1)) state descriptions. For comparison, in a peer-to-peer game, each computer only sends its own state to its peers, thus sending a total of (<i>playerCount</i> − 1) state descriptions.</li>
      <li>The network bandwidth and CPU processing workload fall entirely onto a single server computer, which can easily become a processing bottleneck.</li>
      <li>The network round trip to and from the server may cause players on client computers to experience lag in the game responding to their inputs. (The server does not suffer this lag; hence, the "host advantage" behavior seen in many client/server games.)</li>
      <li>Because the simulation state exists only on a single computer, supporting server migration if that computer goes away is more difficult than when using peer-to-peer networking.</li>
    </ul>

  </div>

  <a name="ID2EZF"></a><h1 class="heading">Extending the Sample</h1><div id="ID2EZF" class="hxnx1">
    

    <p>The actual game data transmitted by this sample is extremely simplistic: it sends network packets on every update (60 times per second), and does not perform any prediction or interpolation to compensate for network latency. This works fine over a local network, but is not suitable for use over the Internet. To make the game playable over the Internet, packets should be sent less often (commonly between 10 and 20 times per second), and prediction algorithms should be used to smooth out the movement of remotely controlled objects.</p>

    <p>
      To get an idea how the increased latency of packets sent over the Internet can affect gameplay, add this line to the <b>HookSessionEvents</b> method:
    </p>

    <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>    networkSession.SimulatedLatency = TimeSpan.FromMilliseconds(200);</pre></pre></td></tr></table></span></div>

    <p>With this simulated latency in place, notice how the server still sees its tank move perfectly smoothly, but there is now a time delay before clients will respond to user inputs, and the tanks on clients move jerkily because the latency is not exactly the same from one packet to the next. This behavior is quite different to what a peer-to-peer game would experience. In a client/server game, only the host experiences a lag-free response, and the clients see lag on all movement of all objects, while in a peer-to-peer game, locally controlled objects always remain smooth, while remote ones suffer from lag.</p>

  </div>

</div><div class="footer" id="footer"><p>© 2008 Microsoft Corporation. All rights reserved.<br>Send feedback to <a href="mailto:xnags@microsoft.com?subject=Documentation Feedback: Client/Server Sample">xnags@microsoft.com</a>.</p></div></div></body></html>